package portal.manager;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.bsc.bean.BeanManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import portal.PortalPanel;
import portal.manager.data.Page;
import portal.manager.data.Template;
import portal.manager.service.PortalManagerService;

/**
 * 
 * @author Sorrentino
 *
 */
public class PortalManagerUtils {

	/**
	 * 
	 * @return
	 */
	private static Logger getLogger() {
		
		return Logger.global;
	}
	
	/**
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isNull( final Object value) {
		return (null==value);
	}

	/**
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isEmpty( final CharSequence value) {
		if(null==value) return true;
		
		String v = value.toString();
		
		if( v.length()==0 ) return true;
		
		return (v.trim().length()==0);
		
	}
	
	/**
	 * 
	 * 
	 * @param context
	 * @return
	 */
	public static PortalManagerService getPortalManagerService( BundleContext context ) {
		
		ServiceReference ref = context.getServiceReference( PortalManagerService.class.getName() );
		
		return (PortalManagerService)context.getService(ref);
	}
	
	/**
	 * 
	 * @throws Exception
	 */
	public static void loadDriver() throws Exception {
        
        String driver = "org.apache.derby.jdbc.EmbeddedDriver";
        Class.forName(driver); 
    
	}

	/**
	 * 
	 * @return
	 * @throws Exception
	 */
	public static Connection getConnection() throws Exception {
        
        String connectionURL = "jdbc:derby:./DerbyDB/portalDB"; 

        Properties p = new Properties();
        p.setProperty("create", "true");
	
        Connection conn = DriverManager.getConnection(connectionURL, p);
        
        conn.setAutoCommit(true);
        
        return conn;
	}
	/**
	 * 
	 * @return
	 * @throws Exception
	 */
	public static Connection getConnection( boolean transactional ) throws Exception {
        
        String connectionURL = "jdbc:derby:./DerbyDB/portalDB"; 

        Properties p = new Properties();
        p.setProperty("create", "true");
	
        Connection conn = DriverManager.getConnection(connectionURL, p);
        
        conn.setAutoCommit(!transactional);
        
        return conn;
	}

	/**
	 * 
	 * @param entityName
	 * @return
	 */
	public static  BeanManager<?> getBeanManager( BundleContext bundleContext, String entityName ) throws Exception {
		
		String filter = MessageFormat.format("(entity={0})", entityName);
		
		ServiceReference[] entityRefs =  bundleContext.getServiceReferences( BeanManager.class.getName(), filter);
		
		if( null==entityRefs || entityRefs.length==0 ) throw new IllegalStateException( "entity not found!");
		
		return (BeanManager<?>) bundleContext.getService(entityRefs[0]);
		
	}

	/**
	 * 
	 * @param panelName
	 * @return
	 * @throws Exception
	 */
	public static PortalPanel[] getPortalPanels( BundleContext bundleContext, String panelName ) throws Exception {
		
		if( panelName!=null &&  panelName.trim().length()==0) return new PortalPanel[0];
		
		String filter = ( null!=panelName) ? MessageFormat.format("(bind.name={0})", panelName) : null;
		
		ServiceReference[] panelRefs = bundleContext.getServiceReferences(PortalPanel.class.getName(), filter);
		
		PortalPanel[] result = null;
		
		if( null==panelRefs || panelRefs.length==0 ) {
			result = new PortalPanel[0];
		}
		else {

			result = new PortalPanel[ panelRefs.length ];
			
			for( int i=0 ; i<panelRefs.length ; ++i ) {
				
				result[i] = (PortalPanel) bundleContext.getService(panelRefs[i]);
			}
		}

		return result;
		
	}

	/**
	 * 
	 * @return
	 * @throws Exception 
	 */
	@SuppressWarnings("unchecked")
	public static Page getPage( final BundleContext bundleContext, final String pageName ) throws Exception {
		Connection conn = null;
		
		Page p = null;

		List<Page.Variable> vars = new ArrayList<Page.Variable>(10);
		
		try {
		
			conn = getPortalManagerService(bundleContext).getConnection();
		
		
			BeanManager<Page> pageMgr = (BeanManager<Page>)getBeanManager( bundleContext, "PAGE" );
			BeanManager<Page.Variable> pageVarMgr = (BeanManager<Page.Variable>)getBeanManager( bundleContext, "PAGE_VARIABLE" );
		
			p = pageMgr.findById(conn,  pageName);
			
			if( null==p ) {
				final String msg = MessageFormat.format("page {0} not found !", pageName);

				getLogger().severe(msg);
				throw new Exception( msg);
			}
			
			pageVarMgr.find(conn, vars, "${templateId}=?", p.getName());
			
			p.setVariables( vars );
		}
		finally {
			
			close( conn );
		}

		return p;
	}

	/**
	 * 
	 * @param bundleContext
	 * @param pageName
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Template getTemplate( final BundleContext bundleContext, final String pageName ) throws Exception {
		Connection conn = null;
		
		Template result = null;

		List<Template.Variable> vars = new ArrayList<Template.Variable>(10);
		
		try {
		
			conn = getPortalManagerService(bundleContext).getConnection();
		
		
			BeanManager<Template> templateMgr = (BeanManager<Template>)getBeanManager( bundleContext, "TEMPLATE" );
			BeanManager<Template.Variable> templateVarMgr = (BeanManager<Template.Variable>)getBeanManager( bundleContext, "TEMPLATE_VARIABLE" );
		
			result = templateMgr.findById(conn,  pageName);
			
			if( null==result ) {
				final String msg = MessageFormat.format("template {0} not found !", pageName);

				getLogger().severe(msg);
				throw new Exception( msg);
			}
			
			templateVarMgr.find(conn, vars, "${templateId}=?", result.getName());
			
			result.setVariables( vars );
		}
		finally {
			
			close( conn );
		}

		return result;
	}

	/**
	 * 
	 * @return
	 * @throws Exception 
	 */
	@SuppressWarnings("unchecked")
	public static Page[] getPages( final BundleContext bundleContext ) throws Exception {
		Connection conn = null;
		
		List<Page> result = new ArrayList<Page>();

		try {
		
			conn = getPortalManagerService(bundleContext).getConnection();
		
		
			BeanManager<Page> pageMgr = (BeanManager<Page>)getBeanManager( bundleContext, "PAGE" );
			BeanManager<Page.Variable> pageVarMgr = (BeanManager<Page.Variable>)getBeanManager( bundleContext, "PAGE_VARIABLE" );
		
			pageMgr.findAll(conn, result, "ORDER BY #{name}" ) ;
			
			for( Page p : result ) {

				List<Page.Variable> vars = new ArrayList<Page.Variable>(10);
				
				pageVarMgr.find(conn, vars, "${templateId}=?", p.getName());
				
				p.setVariables( vars );
			
			}
		}
		finally {
			
			close( conn );
		}

		return result.toArray( new Page[result.size()]);
	}

	/**
	 * 
	 * @param conn
	 */
	public static void close( Connection conn ) {
		
		if( null!=conn ) {
			
			try {
				conn.close();
			} catch (SQLException e) {
				Logger.global.log( Level.WARNING, "connection close", e );
			}
		}
	}
}
